package com.aps.server.dto;

import com.aps.server.entity.ApsOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 排程方案生成请求DTO
 * 用于接收前端"生成方案"按钮提交的完整排程配置数据
 * 
 * @author APS System
 * @date 2025-10-13
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "排程方案生成请求DTO")
public class SchedulingPlanGenerateDto implements Serializable {

    /**
     * 基础参数配置
     * 包含排程的基础参数设定，如开始日期、权重配置等
     */
    @Valid
    @Schema(description = "基础参数配置")
    private BaseParametersDto baseParameters;

    /**
     * 工作时间配置
     * 定义一周内各天的生产时段和加班时段
     */
    @Valid
    @Schema(description = "工作时间配置")
    private List<WorkTimeConfigDto> workTimeConfiguration;

    /**
     * 设备配置
     * 包含选中的设备及其数量、维护计划等信息
     */
    @Valid
    @Schema(description = "设备配置")
    private List<DeviceConfigDto> deviceConfiguration;

    /**
     * 选中的工单ID列表
     * 需要进行排程的工单信息
     */
    @Valid
    @Schema(description = "选中的工单列表")
    private List<SelectedOrderDto> selectedOrderIds;

    /**
     * 工单数量统计
     * 选中工单的总数量
     */
    @Schema(description = "工单数量统计", example = "10")
    private Integer orderCount;

    /**
     * 方案生成时间
     * 前端提交请求的时间戳
     */
    @Schema(description = "方案生成时间", example = "2025-10-13T10:30:00")
    private String generateTime;

    /**
     * 基础参数配置DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "基础参数配置")
    public static class BaseParametersDto {

        /**
         * 约束配置信息
         * 包含约束配置的标题和创建时间
         */
        @Valid
        @NotNull(message = "约束配置信息不能为空")
        @Schema(description = "约束配置信息")
        private ConstraintInfoDto constraintInfo;

        /**
         * 开始日期
         * 排程计划的开始日期
         */
        @NotBlank(message = "开始日期不能为空")
        @Schema(description = "排程开始日期", example = "2025-10-13")
        private String startDate;

        /**
         * 是否加班优先
         * true: 优先使用加班时段进行排程
         * false: 优先使用正常工作时段
         */
        @Schema(description = "是否加班优先", example = "false")
        private Boolean workOverTime;

        /**
         * 是否启用换线次数权重
         */
        @Schema(description = "是否启用换线次数权重", example = "true")
        private Boolean enableChangeLaneRate;

        /**
         * 换线次数权重值 (0-100)
         * 在启用换线次数权重时有效
         */
        @Schema(description = "换线次数权重值", example = "20.00")
        private Double changeLaneRate;

        /**
         * 是否启用交期权重
         */
        @Schema(description = "是否启用交期权重", example = "true")
        private Boolean enableDeliveryRate;

        /**
         * 交期权重值 (0-100)
         * 在启用交期权重时有效
         */
        @Schema(description = "交期权重值", example = "30.00")
        private Double deliveryRate;


        @Schema(description = "是否启用设备利用率权重", example = "true")
        private Boolean enableEquiptUseProbabilityRate;

        @Schema(description = "设备利用率权重值", example = "30.00")
        private Double equiptUseProbabilityRate;
    }

    /**
     * 约束配置信息DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "约束配置信息")
    public static class ConstraintInfoDto {

        /**
         * 约束配置标题
         * 用户自定义的约束配置名称
         */
        @NotBlank(message = "约束配置标题不能为空")
        @Schema(description = "约束配置标题", example = "约束配置-1")
        private String title;

        /**
         * 约束配置创建时间
         */
        @Schema(description = "创建时间", example = "2025-10-13T10:30:00")
        private String createTime;

        private String id; //整体约束配置的id
    }

    /**
     * 工作时间配置DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "工作时间配置")
    public static class WorkTimeConfigDto {

        /**
         * 星期几 (1-7)
         * 1: 星期一, 2: 星期二, ..., 7: 星期日
         */
        @Schema(description = "星期几", example = "1")
        private Integer day;

        /**
         * 星期名称
         */
        @Schema(description = "星期名称", example = "星期一")
        private String dayName;

        /**
         * 生产时段列表
         * 该天的多个生产时段
         */
        @Schema(description = "生产时段列表")
        private List<TimePeriodDto> workPeriods;

        /**
         * 加班时段
         * 该天的加班时段（可选）
         */
        @Schema(description = "加班时段")
        private TimePeriodDto overtimePeriod;

        /**
         * 是否展开显示（前端UI状态，后端可忽略）
         */
        @Schema(description = "是否展开", example = "true")
        private Boolean expanded;
    }

    /**
     * 时间段DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "时间段")
    public static class TimePeriodDto {

        /**
         * 开始时间 (HH:mm格式)
         */
        @NotBlank(message = "开始时间不能为空")
        @Schema(description = "开始时间", example = "08:00")
        private String startTime;

        /**
         * 结束时间 (HH:mm格式)
         */
        @NotBlank(message = "结束时间不能为空")
        @Schema(description = "结束时间", example = "17:00")
        private String endTime;

        /**
         * 错误信息（前端验证用，后端可忽略）
         */
        @Schema(description = "错误信息")
        private String error;
    }

    /**
     * 设备配置DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "设备配置")
    public static class DeviceConfigDto {

        /**
         * 设备ID
         * 对应基础设备表的ID
         */
        @NotBlank(message = "设备ID不能为空")
        @Schema(description = "设备ID", example = "1234567890")
        private String equipId;

        /**
         * 设备编号
         * 设备的唯一编码
         */
        @NotBlank(message = "设备编号不能为空")
        @Schema(description = "设备编号", example = "EQ-001")
        private String equipCode;

        /**
         * 设备名称
         */
        @NotBlank(message = "设备名称不能为空")
        @Schema(description = "设备名称", example = "注塑机A")
        private String equipName;

        /**
         * 设备类型
         * 用于工序匹配
         */
        @Schema(description = "设备类型", example = "注塑机")
        private String equipType;

        /**
         * 设备产能
         * 理论最大产能
         */
        @Schema(description = "设备产能", example = "100件/小时")
        private String equipCapacity;

        /**
         * 设备数量
         * 该类型设备在排程中使用的数量
         */
        @Schema(description = "设备数量", example = "2")
        private Integer quantity;

        /**
         * 维护计划列表
         * 设备的维护计划，在这些时间段内设备不可用
         */
        @Schema(description = "维护计划列表")
        private List<MaintenancePlanDto> maintenancePlans;

        /**
         * 是否展开显示（前端UI状态，后端可忽略）
         */
        @Schema(description = "是否展开", example = "true")
        private Boolean expanded;
    }

    /**
     * 维护计划DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "维护计划")
    public static class MaintenancePlanDto {

        /**
         * 维护计划名称
         */
        @Schema(description = "维护计划名称", example = "月度保养")
        private String name;

        /**
         * 维护开始日期
         */
        @Schema(description = "开始日期", example = "2025-10-15")
        private String startDate;

        /**
         * 维护结束日期
         */
        @Schema(description = "结束日期", example = "2025-10-15")
        private String endDate;

        /**
         * 维护类型
         * daily: 日常保养
         * periodic: 定期检修
         * overhaul: 大修
         * emergency: 紧急维修
         */
        @Schema(description = "维护类型", example = "daily", allowableValues = {"daily", "periodic", "overhaul", "emergency"})
        private String type;

        /**
         * 错误信息（前端验证用，后端可忽略）
         */
        @Schema(description = "错误信息")
        private String error;
    }

    /**
     * 已选工单DTO
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "已选工单")
    public static class SelectedOrderDto {

        /**
         * 工单ID
         * 工单的唯一标识
         */
        @NotBlank(message = "工单ID不能为空")
        @Schema(description = "工单ID", example = "1234567890")
        private String id;

        /**
         * APS工单编号
         * APS系统生成的工单编号
         */
        @Schema(description = "APS工单编号", example = "W-1697123456789")
        private String apsOrderCode;

        /**
         * 订单编号
         * 原始订单编号
         */
        @NotBlank(message = "订单编号不能为空")
        @Schema(description = "订单编号", example = "ORD-2025001")
        private String orderCode;

        /**
         * 产品编号
         * 对应的产品编码
         */
        @NotBlank(message = "产品编号不能为空")
        @Schema(description = "产品编号", example = "PROD-001")
        private String productCode;



        public ApsOrder build(){
            ApsOrder order = new ApsOrder();
            order.setId(id);
            order.setApsOrderCode(apsOrderCode);
            order.setOrderCode(orderCode);
            order.setProductCode(productCode);
            return order;
        }
    }
}

